#ifndef __POLYNOMIAL__
#define __POLYNOMIAL__

#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include "Function.h"

using namespace std;
class Polynomial : public Function
{
 private:
  int n;
  vector<double> Coefficient;
  double x_0;
 public:
  Polynomial(
	     vector<double> _Coefficient,
	     double _x_0
	     ){
    Coefficient = _Coefficient;
    x_0 = _x_0;
    }
  double operator()(double _x)
  {
    n = Coefficient.size();
    double y = 0;
    double z = 1;
    for (int i = 0; i < n; i++)
      {
	y = y + Coefficient[i] * z; 
	z = z * (_x - x_0);
      }
    return y;
  }
  double diff(double _x)
  {
    return 0;
  }
  double diff2(double _x)
  {
    return 0;
  }
};

class B_spline : public Function
{
private:
  vector<double> t;
  int n;
public:
  B_spline(
	   int _n,
	   vector<double> _t){
    t = _t;
    n = _n;
    if (t.size() != n + 2)
      {
	cout<< "B_spline  error" <<endl;
	exit(0);
      }
  }
  double operator()(double _x)
  {
    if (n == 1)
      {
	if (_x > t[0] && _x < t[1])
	  return (_x - t[0])/(t[1] - t[0]);
	else if (_x >= t[1] && _x < t[2])
	  return (t[2] - _x)/(t[2] - t[1]);
	else
	  return 0;
      }
    else
      {
	vector<double> t1(t.begin(),t.end() - 1);
	vector<double> t2(t.begin() + 1,t.end());
	B_spline B_i(n - 1,t1);
	B_spline B_i1(n - 1,t2);
	return (_x - t[0])*B_i(_x)/(t[n] - t[0]) + (t[n + 1] - _x)*B_i1(_x)/(t[n + 1] - t[1]);
      }
  }
  double diff(double _x)
  {
    return 0;
  }
  double diff2(double _x)
  {
    return 0;
  } 
  
};
  
  class Input : public Function 
  {
  private:
    vector<double> Point, Value, Dif, Dif2;
  public:
    Input(
	  vector<double> _Point,
	  vector<double> _Value,
	  vector<double> _Dif,
	  vector<double> _Dif2)
    {
      Point = _Point;
      Value = _Value;
      Dif = _Dif;
      Dif2 = _Dif2;
      if ((Point.size() != Value.size()) || (Point.size() != Dif.size()) || (Point.size() != Dif2.size()))
	{
	  cout<< "input error" <<endl;
	  exit(0);
	}
    }
    
    double operator()(double _x)
    {
      for (int i = 0; i < Point.size(); i++)
	{
	  if (Point[i] == _x)
	    {
	      return Value[i];
	    }
	  cout<< "error:There is no such knot" <<endl;
	  exit(0);
	  return 0;
	}
    }
    
    double diff(double _x)
    {
      for (int i = 0; i < Point.size(); i++)
	{
	  if (Point[i] == _x)
	    {
	      return Dif[i];
	    }
	  cout<< "error: There is no such knot." <<endl;
	  exit(0);
	  return 0;
	}
    }
    
    double diff2(double _x)
    {
      for (int i = 0; i < Point.size(); i++)
	{
	  if (Point[i] == _x)
	    {
	      return Dif2[i];
	    }
	  cout<< "error: There is no such knot." <<endl;
	  exit(0);
	  return 0;
	}
    }
  };
#endif